﻿using System;
using System.IO;
using System.Windows.Forms;

namespace FileExplorer.view
{
	public partial class FileExplorer : Form
	{
		enum FileAction
		{
			None = 0,
			CutFile = 1,
			CopyFile = 2
		}

		TreeNode rootNode = null;
		TreeNode selectedNode = null;
		FileAction curAction;

		public FileExplorer()
		{
			InitializeComponent();

			// init control
			lstViewFile.View = View.List;
			this.trViewFileExplorer.NodeMouseClick +=
				new TreeNodeMouseClickEventHandler(this.treeView1_NodeMouseClick);

			// show file explorer hierachy
			PopulateTreeView();
		}

		private void PopulateTreeView()
		{
			TreeNode nodeDrive = null;
			string dir2 = string.Empty;
			TreeNode childNode = null;

			string[] drives = Environment.GetLogicalDrives();
			rootNode = new TreeNode("My Computer");
			trViewFileExplorer.Nodes.Add(rootNode);

			foreach (string drive in drives)
			{
				DirectoryInfo dirInfo = new DirectoryInfo(drive);

				nodeDrive = new TreeNode();
				nodeDrive.Tag = dirInfo;
				nodeDrive.Text = dirInfo.Name;

				rootNode.Nodes.Add(nodeDrive);
				nodeDrive.EnsureVisible();

				// add child directory
				try
				{
					//add dirs under drive
					foreach (DirectoryInfo childDir in dirInfo.GetDirectories())
					{
						if (FileAttributes.Directory == (FileAttributes.Directory & childDir.Attributes))
						{
							childNode = new TreeNode();
							childNode.Tag = childDir;
							childNode.Text = childDir.Name;
							nodeDrive.Nodes.Add(childNode);
						};
					}
				}
				catch (Exception) { }

				selectedNode = rootNode.FirstNode;
				RefreshView();
			}

			trViewFileExplorer.Refresh();
		}

		void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			selectedNode = e.Node;
			RefreshView();
		}

		private void tbAdrressBar_KeyUp(object sender, KeyEventArgs e)
		{
			TreeNode searchNode = null;

			if (Keys.Enter == e.KeyCode && Directory.Exists(tbAdrressBar.Text))
			{
				// find node
				searchNode = FindNode(tbAdrressBar.Text);
				if (null != searchNode)
				{
					selectedNode = searchNode;
					RefreshView();
				}
			}
			else if (Keys.Enter == e.KeyCode)
			{
				tbAdrressBar.Text = ((DirectoryInfo) selectedNode.Tag).FullName;
			}
		}

		public void RefreshView()
		{
			if (null != selectedNode)
			{
				DirectoryInfo nodeDirInfo = (DirectoryInfo)selectedNode.Tag;
				ListViewItem.ListViewSubItem[] subItems;
				ListViewItem item = null;
				try
				{
					// Attempt to get a list of security permissions from the folder. 
					// This will raise an exception if the path is read only or do not have access to view the permissions. 
					System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(nodeDirInfo.FullName);


					// Add Directory to Tree view
					FindSubDirAndAddNode(ref selectedNode);
					trViewFileExplorer.SelectedNode = selectedNode;

					// Add File to List view
					lstViewFile.Items.Clear();
					foreach (FileInfo file in nodeDirInfo.GetFiles())
					{
						item = new ListViewItem(file.Name, 1);
						subItems = new ListViewItem.ListViewSubItem[]
								{ 
									new ListViewItem.ListViewSubItem(item, "File"), 
									new ListViewItem.ListViewSubItem(item, file.LastAccessTime.ToShortDateString())
								};

						item.SubItems.AddRange(subItems);
						lstViewFile.Items.Add(item);
					}
				}
				catch (UnauthorizedAccessException)
				{
					MessageBox.Show("Access is denied!\n \" " + nodeDirInfo.FullName + "\" ", "Allert",
						MessageBoxButtons.OK, MessageBoxIcon.Warning);
				}
				catch (InvalidOperationException) { }

				// change address bar
				tbAdrressBar.Text = ((DirectoryInfo)selectedNode.Tag).FullName;

				lstViewFile.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
				trViewFileExplorer.Refresh();
			}
		}

		private bool AddDirectoryNode()
		{
			bool bResult = false;

			return bResult;
		}

		private TreeNode FindNode(string sDirPath)
		{
			string[] dirNames = sDirPath.Split('\\');
			TreeNode parrentNode = rootNode;

			foreach( string dirName in dirNames)
			{
				FindSubDirAndAddNode(ref parrentNode);

				foreach( TreeNode nodechild in parrentNode.Nodes)
				{
					if( nodechild.Text.Contains(dirName))
					{
						parrentNode = nodechild;
						break;
					}
				}
			}

			return parrentNode;
		}

		private bool FindSubDirAndAddNode(ref TreeNode parrentNode)
		{
			bool bResult		= false;
			TreeNode childNode	= null;
			DirectoryInfo nodeDirInfo = (DirectoryInfo) parrentNode.Tag;
			try
			{
				System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(nodeDirInfo.FullName);

				if (nodeDirInfo.GetDirectories().Length > 0)
				{
					parrentNode.Nodes.Clear();

					foreach (DirectoryInfo dir in nodeDirInfo.GetDirectories())
					{
						if (FileAttributes.Directory == (FileAttributes.Directory & dir.Attributes))
						{
							childNode = new TreeNode();
							childNode.Tag = dir;
							childNode.Text = dir.Name;
							parrentNode.Nodes.Add(childNode);
						}
					}
				}

				bResult = true;
			}
			catch(Exception){}

			return bResult;
		}
	}
}
